package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskListBO;
import com.ssy.lingxi.member.merchant.model.bo.WorkflowTaskResultBO;
import com.ssy.lingxi.member.merchant.model.constant.MemberAppraisalItemStatusEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberAppraisalItemTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberAppraisalStatusEnum;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.NamePageVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.*;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.*;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberHistoryService;
import com.ssy.lingxi.member.merchant.service.feign.IMessageFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IReportFeignService;
import com.ssy.lingxi.member.merchant.service.feign.IWorkflowFeignService;
import com.ssy.lingxi.member.merchant.service.web.IMemberAppraisalService;
import com.ssy.lingxi.member.merchant.utils.CodeUtils;
import com.ssy.lingxi.member.merchant.utils.FileObjectUtil;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.report.api.enums.MemberKpiOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.MemberRectifyOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.workflow.api.model.contant.ProcessTaskStatusEnum;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员考评服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/5/17
 */
@Service
public class MemberAppraisalServiceImpl implements IMemberAppraisalService {

    private static final Logger log = LoggerFactory.getLogger(MemberAppraisalServiceImpl.class);

    @Resource
    private IBaseMemberCacheService memberCacheService;
    @Resource
    private IBaseMemberHistoryService memberHistoryService;
    @Resource
    private IWorkflowFeignService workflowFeignService;
    @Resource
    private MemberAppraisalRepository memberAppraisalRepository;
    @Resource
    private MemberAppraisalItemRepository memberAppraisalItemRepository;
    @Resource
    private MemberRelationRepository memberRelationRepository;
    @Resource
    private MemberUserRepository memberUserRepository;
    @Resource
    private MemberConfigAppraisalItemRepository memberConfigAppraisalItemRepository;
    @Resource
    private IMessageFeignService messageFeignService;
    @Resource
    private IReportFeignService reportFeignService;

    @Override
    public Wrapper<List<StatusVO>> listMemberAppraisalStatus(HttpHeaders headers) {
        List<StatusVO> statusVOList = Stream.of(MemberAppraisalStatusEnum.values()).map(e -> {
            StatusVO statusVO = new StatusVO();
            statusVO.setCode(e.getCode());
            statusVO.setMessage(e.getMessage());
            return statusVO;
        }).collect(Collectors.toList());

        return Wrapper.success(statusVOList);
    }

    @Override
    public Wrapper<PageData<MemberAppraisalSubmitPageQueryVO>> pageSummaryMemberAppraisal(HttpHeaders headers, MemberAppraisalSummaryPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, Objects.isNull(pageVO.getStatus()) ? Collections.emptyList() : Collections.singletonList(pageVO.getStatus()), pageVO);

        List<MemberAppraisalSubmitPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalSubmitPageQueryVO pageQueryVO = new MemberAppraisalSubmitPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore());
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));

            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    /**
     * 会员信息 - 会员档案 - 分页查询考评列表
     * @param member 上级会员
     * @param role 上级会员角色
     * @param subMember 下级会员
     * @param subRole 下级会员角色
     * @param current 当前页
     * @param pageSize 每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberAppraisalPageQueryVO>> pageMemberAppraisal(MemberDO member, RoleDO role, MemberDO subMember, RoleDO subRole, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberAppraisalDO> pageList = memberAppraisalRepository.findAll((Specification<MemberAppraisalDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("member").as(MemberDO.class), member));
            predicateList.add(cb.equal(root.get("role").as(RoleDO.class), role));
            predicateList.add(cb.equal(root.get("subMember").as(MemberDO.class), subMember));
            predicateList.add(cb.equal(root.get("subRole").as(RoleDO.class), subRole));
            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(e -> {
            MemberAppraisalPageQueryVO pageQueryVO = new MemberAppraisalPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore() == null ? "" : ServiceConfig.BIG_DECIMAL_FORMAT.format(e.getTotalScore()));
            return pageQueryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalAddPageQueryVO>> pageWaitAddMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, Collections.singletonList(MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode()), pageVO);

        List<MemberAppraisalAddPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalAddPageQueryVO pageQueryVO = new MemberAppraisalAddPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));
            pageQueryVO.setUpdateOrDel(MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode().equals(e.getStatus()));
            pageQueryVO.setPublish(MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode().equals(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalGradePageQueryVO>> pageWaitGradeMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        Page<MemberAppraisalDO> pageList = memberAppraisalRepository.findAll((Specification<MemberAppraisalDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            // 一对多关联, 查询记录数量为n倍, 以主表去重
            query.distinct(true);
            predicateList.add(cb.equal(root.get("member").as(MemberDO.class), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("role").as(RoleDO.class), loginUser.getMemberRoleId()));
            // 查询的是待提交考评结果的状态
            predicateList.add(cb.equal(root.get("status"), MemberAppraisalStatusEnum.WAIT_SUBMIT.getCode()));

            Join<MemberAppraisalDO, MemberAppraisalItemDO> appraisalItemJoin = root.join("items", JoinType.LEFT);
            predicateList.add(cb.equal(appraisalItemJoin.get("status"), MemberAppraisalItemStatusEnum.WAIT_GRADE.getCode()));
            predicateList.add(cb.equal(appraisalItemJoin.get("sendAppraisal"), EnableDisableStatus.ENABLE.getCode()));

            Join<MemberAppraisalItemDO, MemberUserDO> memberUserJoin = appraisalItemJoin.join("byUser", JoinType.LEFT);
            predicateList.add(cb.equal(memberUserJoin.get("id"), loginUser.getUserId()));

            if (StringUtils.isNotEmpty(pageVO.getName())) {
                Join<MemberAppraisalDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                predicateList.add(cb.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateStart(pageVO.getAppraisalDayStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("appraisalTimeStart"), startDate));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateEnd(pageVO.getAppraisalDayEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("appraisalTimeEnd"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberAppraisalGradePageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalGradePageQueryVO pageQueryVO = new MemberAppraisalGradePageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            // ===========用于展示============ start
            pageQueryVO.setStatus(MemberAppraisalStatusEnum.WAIT_GRADE.getCode());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.WAIT_GRADE.getMessage());
            // ===========用于展示============ end
            pageQueryVO.setGrade(MemberAppraisalItemStatusEnum.WAIT_GRADE.getCode().equals(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalSubmitPageQueryVO>> pageWaitSubmitMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        List<Integer> statusLists = Arrays.asList(MemberAppraisalStatusEnum.WAIT_SUBMIT.getCode(),
                MemberAppraisalStatusEnum.WAIT_AUDIT_1_REJECT.getCode(),
                MemberAppraisalStatusEnum.WAIT_AUDIT_2_REJECT.getCode());

        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, statusLists, pageVO);

        List<MemberAppraisalSubmitPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalSubmitPageQueryVO pageQueryVO = new MemberAppraisalSubmitPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));
            pageQueryVO.setSubmitOrUpdate(statusLists.contains(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalAuditPageQueryVO>> pageWaitAuditOneMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, Collections.singletonList(MemberAppraisalStatusEnum.WAIT_AUDIT_1.getCode()), pageVO);

        List<MemberAppraisalAuditPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalAuditPageQueryVO pageQueryVO = new MemberAppraisalAuditPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore());
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));
            pageQueryVO.setAudit(MemberAppraisalStatusEnum.WAIT_AUDIT_1.getCode().equals(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalAuditPageQueryVO>> pageWaitAuditTwoMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, Collections.singletonList(MemberAppraisalStatusEnum.WAIT_AUDIT_2.getCode()), pageVO);

        List<MemberAppraisalAuditPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalAuditPageQueryVO pageQueryVO = new MemberAppraisalAuditPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore());
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));
            pageQueryVO.setAudit(MemberAppraisalStatusEnum.WAIT_AUDIT_2.getCode().equals(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<MemberAppraisalNotificationPageQueryVO>> pageWaitNotificationMemberAppraisal(HttpHeaders headers, MemberAppraisalPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Page<MemberAppraisalDO> pageList = baseMemberAppraisalPage(loginUser, Collections.singletonList(MemberAppraisalStatusEnum.WAIT_NOTIFICATION.getCode()), pageVO);

        List<MemberAppraisalNotificationPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalNotificationPageQueryVO pageQueryVO = new MemberAppraisalNotificationPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setName(e.getSubMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore());
            pageQueryVO.setStatus(e.getStatus());
            pageQueryVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(e.getStatus()));
            pageQueryVO.setNotification(MemberAppraisalStatusEnum.WAIT_NOTIFICATION.getCode().equals(e.getStatus()));
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    private Page<MemberAppraisalDO> baseMemberAppraisalPage(UserLoginCacheDTO loginUser, List<Integer> statusList, MemberAppraisalPageVO pageVO) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        return memberAppraisalRepository.findAll((Specification<MemberAppraisalDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            if (!CollectionUtils.isEmpty(statusList)) {
                predicateList.add(cb.and(root.get("status").in(statusList)));
            }

            predicateList.add(cb.equal(root.get("member").as(MemberDO.class), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("role").as(RoleDO.class), loginUser.getMemberRoleId()));

            if (StringUtils.isNotEmpty(pageVO.getName())) {
                Join<MemberAppraisalDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                predicateList.add(cb.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateStart(pageVO.getAppraisalDayStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("appraisalTimeStart"), startDate));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateEnd(pageVO.getAppraisalDayEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("appraisalTimeEnd"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);
    }

    @Override
    public Wrapper<PageData<MemberAppraisalSubResultPageQueryVO>> pageSubResultMemberAppraisal(HttpHeaders headers, MemberAppraisalSubResultPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        Page<MemberAppraisalDO> pageList = memberAppraisalRepository.findAll((Specification<MemberAppraisalDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("notifyMember"), EnableDisableStatus.ENABLE.getCode()));

            predicateList.add(cb.equal(root.get("subMember"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("subRole"), loginUser.getMemberRoleId()));

            if (StringUtils.isNotEmpty(pageVO.getUpperName())) {
                Join<MemberAppraisalDO, MemberDO> upperMemberJoin = root.join("member", JoinType.LEFT);
                predicateList.add(cb.like(upperMemberJoin.get("subject"), "%" + pageVO.getUpperName() + "%"));
            }

            if (StringUtils.isNotEmpty(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateStart(pageVO.getAppraisalDayStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("appraisalTimeStart"), startDate));
            }

            if (Objects.nonNull(pageVO.getAppraisalDayEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateEnd(pageVO.getAppraisalDayEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("appraisalTimeEnd"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberAppraisalSubResultPageQueryVO> resultList = pageList.stream().map(e -> {
            MemberAppraisalSubResultPageQueryVO pageQueryVO = new MemberAppraisalSubResultPageQueryVO();
            pageQueryVO.setId(e.getId());
            pageQueryVO.setAppraisalNo(e.getAppraisalNo());
            pageQueryVO.setSubject(e.getSubject());
            pageQueryVO.setUpperName(e.getMember().getName());
            pageQueryVO.setAppraisalDayStart(DateTimeUtil.formatDate(e.getAppraisalTimeStart()));
            pageQueryVO.setAppraisalDayEnd(DateTimeUtil.formatDate(e.getAppraisalTimeEnd()));
            pageQueryVO.setCompleteDay(DateTimeUtil.formatDate(e.getCompleteTime()));
            pageQueryVO.setTotalScore(e.getTotalScore());
            return pageQueryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<MemberAppraisalSubResultVO> getSubMemberAppraisalResult(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberAppraisalSubResultVO memberAppraisalResultVO = new MemberAppraisalSubResultVO();
        memberAppraisalResultVO.setId(memberAppraisalDO.getId());
        memberAppraisalResultVO.setAppraisalNo(memberAppraisalDO.getAppraisalNo());
        memberAppraisalResultVO.setStatus(memberAppraisalDO.getStatus());
        memberAppraisalResultVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()));
        memberAppraisalResultVO.setMemberId(memberAppraisalDO.getMember().getId());
        memberAppraisalResultVO.setRoleId(memberAppraisalDO.getRole().getId());
        memberAppraisalResultVO.setSubject(memberAppraisalDO.getSubject());
        memberAppraisalResultVO.setUpperName(memberAppraisalDO.getMember().getName());
        memberAppraisalResultVO.setAppraisalDayStart(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeStart()));
        memberAppraisalResultVO.setAppraisalDayEnd(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeEnd()));
        memberAppraisalResultVO.setCompleteDay(DateTimeUtil.formatDate(memberAppraisalDO.getCompleteTime()));
        memberAppraisalResultVO.setAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getAttachments()));
        memberAppraisalResultVO.setTotalScore(memberAppraisalDO.getTotalScore());
        memberAppraisalResultVO.setResult(memberAppraisalDO.getResult());
        memberAppraisalResultVO.setResultAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getResultAttachments()));

        List<MemberAppraisalItemDO> memberAppraisalItems = memberAppraisalItemRepository.findAll((Specification<MemberAppraisalItemDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            Join<MemberAppraisalItemDO, MemberAppraisalDO> appraisalJoin = root.join("appraisal", JoinType.LEFT);
            predicateList.add(cb.equal(appraisalJoin.get("id"), memberAppraisalDO.getId()));

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        });

        List<MemberAppraisalItemVO> items = memberAppraisalItems.stream().map(e -> {
            MemberAppraisalItemVO itemVO = new MemberAppraisalItemVO();
            itemVO.setId(e.getId());
            itemVO.setName(e.getName());
            itemVO.setContent(e.getContent());
            itemVO.setType(e.getType());
            itemVO.setUserId(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getId() : 0L);
            itemVO.setUserName(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getName() : "系统");
            itemVO.setSendAppraisal(e.getSendAppraisal());
            itemVO.setScoreWeight(e.getScoreWeight());
            itemVO.setGrade(e.getGrade());
            itemVO.setScore(e.getScore());
            itemVO.setTemplates(FileObjectUtil.toVOList(e.getTemplates()));
            itemVO.setAppraisalReport(FileObjectUtil.toVOList(e.getReports()));
            return itemVO;
        }).collect(Collectors.toList());
        memberAppraisalResultVO.setItems(items);

        return Wrapper.success(memberAppraisalResultVO);
    }

    @Override
    public Wrapper<MemberAppraisalResultVO> getMemberAppraisalResult(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberAppraisalResultVO memberAppraisalResultVO = new MemberAppraisalResultVO();
        memberAppraisalResultVO.setId(memberAppraisalDO.getId());
        memberAppraisalResultVO.setAppraisalNo(memberAppraisalDO.getAppraisalNo());
        memberAppraisalResultVO.setStatus(memberAppraisalDO.getStatus());
        memberAppraisalResultVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()));
        memberAppraisalResultVO.setSubMemberId(memberAppraisalDO.getSubMember().getId());
        memberAppraisalResultVO.setSubRoleId(memberAppraisalDO.getSubRole().getId());
        memberAppraisalResultVO.setSubject(memberAppraisalDO.getSubject());
        memberAppraisalResultVO.setName(memberAppraisalDO.getSubMember().getName());
        memberAppraisalResultVO.setAppraisalDayStart(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeStart()));
        memberAppraisalResultVO.setAppraisalDayEnd(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeEnd()));
        memberAppraisalResultVO.setCompleteDay(DateTimeUtil.formatDate(memberAppraisalDO.getCompleteTime()));
        memberAppraisalResultVO.setAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getAttachments()));
        memberAppraisalResultVO.setTotalScore(memberAppraisalDO.getTotalScore());
        memberAppraisalResultVO.setResult(memberAppraisalDO.getResult());
        memberAppraisalResultVO.setNotifyMember(memberAppraisalDO.getNotifyMember());
        memberAppraisalResultVO.setResultAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getResultAttachments()));

        List<MemberAppraisalItemDO> memberAppraisalItems = memberAppraisalDO.getItems();
        List<MemberAppraisalItemVO> items = memberAppraisalItems.stream().map(e -> {
            MemberAppraisalItemVO itemVO = new MemberAppraisalItemVO();
            itemVO.setId(e.getId());
            itemVO.setName(e.getName());
            itemVO.setContent(e.getContent());
            itemVO.setType(e.getType());
            itemVO.setUserId(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getId() : 0L);
            itemVO.setUserName(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getName() : "系统");
            itemVO.setSendAppraisal(e.getSendAppraisal());
            itemVO.setScoreWeight(e.getScoreWeight());
            itemVO.setGrade(e.getGrade());
            itemVO.setScore(e.getScore());
            itemVO.setTemplates(FileObjectUtil.toVOList(e.getTemplates()));
            itemVO.setAppraisalReport(FileObjectUtil.toVOList(e.getReports()));
            return itemVO;
        }).collect(Collectors.toList());
        memberAppraisalResultVO.setItems(items);


        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listMemberProcessSteps(memberAppraisalDO.getMember().getId(), ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        if (StringUtils.isBlank(memberAppraisalDO.getTaskId()) && MemberAppraisalStatusEnum.SUBMIT_NOTIFICATION.getCode().equals(memberAppraisalDO.getStatus())) {
            memberAppraisalResultVO.setCurrentStep(7);
        } else {
            memberAppraisalResultVO.setCurrentStep((result.getData().getCurrentStep()));
        }
        memberAppraisalResultVO.setVerifySteps(result.getData().getStepList());
        memberAppraisalResultVO.setHistory(memberHistoryService.listMemberAppraisalHistory(memberAppraisalDO.getId()));

        return Wrapper.success(memberAppraisalResultVO);
    }

    @Override
    public Wrapper<MemberAppraisalVO> getMemberAppraisal(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberAppraisalVO memberAppraisalVO = new MemberAppraisalVO();
        memberAppraisalVO.setId(memberAppraisalDO.getId());
        memberAppraisalVO.setAppraisalNo(memberAppraisalDO.getAppraisalNo());
        memberAppraisalVO.setStatus(memberAppraisalDO.getStatus());
        memberAppraisalVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()));
        memberAppraisalVO.setSubMemberId(memberAppraisalDO.getSubMember().getId());
        memberAppraisalVO.setSubRoleId(memberAppraisalDO.getSubRole().getId());
        memberAppraisalVO.setSubject(memberAppraisalDO.getSubject());
        memberAppraisalVO.setName(memberAppraisalDO.getSubMember().getName());
        memberAppraisalVO.setAppraisalDayStart(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeStart()));
        memberAppraisalVO.setAppraisalDayEnd(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeEnd()));
        memberAppraisalVO.setCompleteDay(DateTimeUtil.formatDate(memberAppraisalDO.getCompleteTime()));
        memberAppraisalVO.setAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getAttachments()));

        List<MemberAppraisalItemDO> memberAppraisalItems = memberAppraisalDO.getItems();
        List<MemberAppraisalItemVO> items = memberAppraisalItems.stream().map(e -> {
            MemberAppraisalItemVO itemVO = new MemberAppraisalItemVO();
            itemVO.setId(e.getId());
            itemVO.setName(e.getName());
            itemVO.setContent(e.getContent());
            itemVO.setType(e.getType());
            itemVO.setUserId(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getId() : 0L);
            itemVO.setUserName(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getName() : "系统");
            itemVO.setSendAppraisal(e.getSendAppraisal());
            itemVO.setScoreWeight(e.getScoreWeight());
            itemVO.setGrade(e.getGrade());
            itemVO.setScore(e.getScore());
            itemVO.setTemplates(FileObjectUtil.toVOList(e.getTemplates()));
            itemVO.setAppraisalReport(FileObjectUtil.toVOList(e.getReports()));
            return itemVO;
        }).collect(Collectors.toList());
        memberAppraisalVO.setItems(items);


        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listMemberProcessSteps(memberAppraisalDO.getMember().getId(), ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        if (StringUtils.isBlank(memberAppraisalDO.getTaskId()) && MemberAppraisalStatusEnum.SUBMIT_NOTIFICATION.getCode().equals(memberAppraisalDO.getStatus())) {
            memberAppraisalVO.setCurrentStep(7);
        } else {
            memberAppraisalVO.setCurrentStep((result.getData().getCurrentStep()));
        }
        memberAppraisalVO.setVerifySteps(result.getData().getStepList());
        memberAppraisalVO.setHistory(memberHistoryService.listMemberAppraisalHistory(memberAppraisalDO.getId()));

        return Wrapper.success(memberAppraisalVO);
    }

    @Override
    public Wrapper<MemberAppraisalVO> getWaitGradeMemberAppraisal(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberAppraisalVO memberAppraisalVO = new MemberAppraisalVO();
        memberAppraisalVO.setId(memberAppraisalDO.getId());
        memberAppraisalVO.setAppraisalNo(memberAppraisalDO.getAppraisalNo());
        memberAppraisalVO.setStatus(memberAppraisalDO.getStatus());
        memberAppraisalVO.setStatusName(MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()));
        memberAppraisalVO.setSubMemberId(memberAppraisalDO.getSubMember().getId());
        memberAppraisalVO.setSubRoleId(memberAppraisalDO.getSubRole().getId());
        memberAppraisalVO.setSubject(memberAppraisalDO.getSubject());
        memberAppraisalVO.setName(memberAppraisalDO.getSubMember().getName());
        memberAppraisalVO.setAppraisalDayStart(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeStart()));
        memberAppraisalVO.setAppraisalDayEnd(DateTimeUtil.formatDate(memberAppraisalDO.getAppraisalTimeEnd()));
        memberAppraisalVO.setCompleteDay(DateTimeUtil.formatDate(memberAppraisalDO.getCompleteTime()));
        memberAppraisalVO.setAttachments(FileObjectUtil.toVOList(memberAppraisalDO.getAttachments()));

        List<MemberAppraisalItemDO> memberAppraisalItems = memberAppraisalItemRepository.findAll((Specification<MemberAppraisalItemDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("appraisal").as(MemberAppraisalDO.class), memberAppraisalDO.getId()));
            predicateList.add(cb.equal(root.get("byUser").as(MemberUserDO.class), loginUser.getUserId()));

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        });

        List<MemberAppraisalItemVO> items = memberAppraisalItems.stream().map(e -> {
            MemberAppraisalItemVO itemVO = new MemberAppraisalItemVO();
            itemVO.setId(e.getId());
            itemVO.setName(e.getName());
            itemVO.setContent(e.getContent());
            itemVO.setType(e.getType());
            itemVO.setUserId(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getId() : 0L);
            itemVO.setUserName(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(e.getType()) ? e.getByUser().getName() : "系统");
            itemVO.setSendAppraisal(e.getSendAppraisal());
            itemVO.setScoreWeight(e.getScoreWeight());
            itemVO.setGrade(e.getGrade());
            itemVO.setScore(e.getScore());
            itemVO.setTemplates(FileObjectUtil.toVOList(e.getTemplates()));
            itemVO.setAppraisalReport(FileObjectUtil.toVOList(e.getReports()));
            return itemVO;
        }).collect(Collectors.toList());
        memberAppraisalVO.setItems(items);


        Wrapper<WorkflowTaskListBO> result = workflowFeignService.listMemberProcessSteps(memberAppraisalDO.getMember().getId(), ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        if (StringUtils.isBlank(memberAppraisalDO.getTaskId()) && MemberAppraisalStatusEnum.SUBMIT_NOTIFICATION.getCode().equals(memberAppraisalDO.getStatus())) {
            memberAppraisalVO.setCurrentStep(7);
        } else {
            memberAppraisalVO.setCurrentStep((result.getData().getCurrentStep()));
        }
        memberAppraisalVO.setVerifySteps(result.getData().getStepList());
        memberAppraisalVO.setHistory(memberHistoryService.listMemberAppraisalHistory(memberAppraisalDO.getId()));

        return Wrapper.success(memberAppraisalVO);
    }

    @Override
    public Wrapper<PageData<MemberConfigAppraisalItemQueryPageVO>> pageMemberConfigAppraisalItem(HttpHeaders headers, NamePageVO pageVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").descending());

        Page<MemberConfigAppraisalItemDO> pageList = memberConfigAppraisalItemRepository.findAll((Specification<MemberConfigAppraisalItemDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("status"), EnableDisableStatus.ENABLE.getCode()));

            if (StringUtils.isNotEmpty(pageVO.getName())) {
                predicateList.add(cb.like(root.get("name"), "%" + pageVO.getName() + "%"));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return query.where(predicateList.toArray(p)).getRestriction();
        }, page);

        List<MemberConfigAppraisalItemQueryPageVO> resultList = pageList.stream().map(e -> {
            MemberConfigAppraisalItemQueryPageVO resultPageVO = new MemberConfigAppraisalItemQueryPageVO();
            resultPageVO.setId(e.getId());
            resultPageVO.setName(e.getName());
            resultPageVO.setTypeDesc(e.getTypeDesc());
            resultPageVO.setStatus(e.getStatus());
            resultPageVO.setRoleName(e.getRole().getRoleName());
            resultPageVO.setType(e.getType());
            return resultPageVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), resultList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> addMemberAppraisal(HttpHeaders headers, MemberAppraisalAddVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), addVO.getSubMemberId(), addVO.getSubRoleId());
        if (relationDO == null
                || !relationDO.getMemberId().equals(loginUser.getMemberId())
                || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        // 查询考评用户
        List<MemberUserDO> users = Collections.emptyList();
        if (!CollectionUtils.isEmpty(addVO.getItems())) {
            // 过滤掉userId为0的数据
            Set<Long> userIds = addVO.getItems().stream().map(MemberAppraisalItemAddVO::getUserId).filter(userId -> userId != 0).collect(Collectors.toSet());
            users = memberUserRepository.findAllById(userIds);
            if (users.size() != userIds.size()) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }
        }
        Map<Long, MemberUserDO> userMap = users.stream().collect(Collectors.toMap(MemberUserDO::getId, e -> e));

        // 判断考评项目的权重和, 取值范围0-100
        Integer totalScoreWeight = addVO.getItems().stream().map(MemberAppraisalItemAddVO::getScoreWeight).reduce(0, Integer::sum);
        if (totalScoreWeight > 100) {
            return Wrapper.fail(ResponseCode.MC_MS_APPRAISAL_ITEM_TOTAL_SCORE_WEIGHT);
        }

        MemberAppraisalDO memberAppraisalDO = new MemberAppraisalDO();
        memberAppraisalDO.setStatus(MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode());
        memberAppraisalDO.setSubject(addVO.getSubject());
        memberAppraisalDO.setSubMember(relationDO.getSubMember());
        memberAppraisalDO.setSubRole(relationDO.getSubRole());
        memberAppraisalDO.setAppraisalTimeStart(DateTimeUtil.parseConcatDateTime(addVO.getAppraisalDayStart()));
        memberAppraisalDO.setAppraisalTimeEnd(DateTimeUtil.parseConcatDateTime(addVO.getAppraisalDayEnd()));
        memberAppraisalDO.setCompleteTime(DateTimeUtil.parseConcatDateTime(addVO.getCompleteDay()));
        memberAppraisalDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberAppraisalDO.setMember(relationDO.getMember());
        memberAppraisalDO.setRole(relationDO.getRole());
        memberAppraisalDO.setCreateTime(LocalDateTime.now());
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        memberAppraisalDO.setAppraisalNo("PA" + CodeUtils.digits32(memberAppraisalDO.getId(), 4));
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        // TODO 计算已配置的项目
        List<MemberAppraisalItemDO> items = addVO.getItems().stream().map(e -> {
            MemberAppraisalItemDO item = new MemberAppraisalItemDO();
            // 项目类型
            Integer itemType = Objects.isNull(e.getType()) ? MemberAppraisalItemTypeEnum.DEFINITION.getCode() : e.getType();
            item.setAppraisal(memberAppraisalDO);
            item.setType(itemType);
            item.setName(e.getName());
            item.setContent(e.getContent());
            item.setStatus(EnableDisableStatus.DISABLE.getCode());
            item.setByUser(MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(itemType) ? userMap.get(e.getUserId()) : null);
            item.setSendAppraisal(Objects.isNull(e.getSendAppraisal()) ? EnableDisableStatus.DISABLE.getCode() : e.getSendAppraisal());
            item.setScoreWeight(e.getScoreWeight());
            item.setTemplates(FileObjectUtil.toBOList(e.getTemplates()));
            if (Objects.isNull(e.getSendAppraisal()) || EnableDisableStatus.DISABLE.getCode().equals(e.getSendAppraisal())) {
                BigDecimal grade = Objects.isNull(e.getGrade()) ? BigDecimal.ZERO : e.getGrade();
                item.setGrade(grade);
                item.setScore(item.getScoreWeight() == 0 ? grade : grade.multiply(new BigDecimal(item.getScoreWeight() / 100).setScale(2, BigDecimal.ROUND_DOWN)));
                item.setReports(FileObjectUtil.toBOList(e.getReports()));
            }
            return item;
        }).collect(Collectors.toList());

        memberAppraisalItemRepository.saveAll(items);

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.startMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员考评新增, 调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberAppraisalDO.setStatus(result.getData().getInnerStatus());
        memberAppraisalDO.setTaskId(result.getData().getTaskId());
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        // 首页统计
        reportFeignService.executeIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberRectifyOperateTypeEnum.TO_BE_SEND_NOTICE_COUNT.getCode(),
                memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

        // 发送消息
        messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                MessageTemplateCode.mc_appraisal_publish, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> updateMemberAppraisal(HttpHeaders headers, MemberAppraisalUpdateVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(addVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode().equals(memberAppraisalDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), addVO.getSubMemberId(), addVO.getSubRoleId());
        if (relationDO == null
                || !relationDO.getMemberId().equals(loginUser.getMemberId())
                || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        // 查询考评用户
        List<MemberUserDO> users = Collections.emptyList();
        if (!CollectionUtils.isEmpty(addVO.getItems())) {
            Set<Long> userIds = addVO.getItems().stream().map(MemberAppraisalItemAddVO::getUserId).filter(userId -> userId != 0).collect(Collectors.toSet());
            users = memberUserRepository.findAllById(userIds);
            if (users.size() != userIds.size()) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }
        }
        Map<Long, MemberUserDO> userMap = users.stream().collect(Collectors.toMap(MemberUserDO::getId, e -> e));

        // 判断考评项目的权重和, 取值范围0-100
        Integer totalScoreWeight = addVO.getItems().stream().map(MemberAppraisalItemAddVO::getScoreWeight).reduce(0, Integer::sum);
        if (totalScoreWeight > 100) {
            return Wrapper.fail(ResponseCode.MC_MS_APPRAISAL_ITEM_TOTAL_SCORE_WEIGHT);
        }

        memberAppraisalDO.setSubject(addVO.getSubject());
        memberAppraisalDO.setSubMember(relationDO.getSubMember());
        memberAppraisalDO.setSubRole(relationDO.getSubRole());
        memberAppraisalDO.setAppraisalTimeStart(DateTimeUtil.parseConcatDateTime(addVO.getAppraisalDayStart()));
        memberAppraisalDO.setAppraisalTimeEnd(DateTimeUtil.parseConcatDateTime(addVO.getAppraisalDayEnd()));
        memberAppraisalDO.setCompleteTime(DateTimeUtil.parseConcatDateTime(addVO.getCompleteDay()));
        memberAppraisalDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        memberAppraisalItemRepository.deleteByAppraisalId(memberAppraisalDO.getId());

        List<MemberAppraisalItemDO> items = addVO.getItems().stream().map(e -> {
            MemberAppraisalItemDO item = new MemberAppraisalItemDO();
            item.setAppraisal(memberAppraisalDO);
            item.setType(Objects.isNull(e.getType()) ? MemberAppraisalItemTypeEnum.DEFINITION.getCode() : e.getType());
            item.setName(e.getName());
            item.setContent(e.getContent());
            item.setByUser(userMap.get(e.getUserId()));
            item.setSendAppraisal(Objects.isNull(e.getSendAppraisal()) ? EnableDisableStatus.DISABLE.getCode() : e.getSendAppraisal());
            item.setScoreWeight(e.getScoreWeight());
            item.setTemplates(FileObjectUtil.toBOList(e.getTemplates()));
            if (Objects.isNull(e.getSendAppraisal()) || EnableDisableStatus.DISABLE.getCode().equals(e.getSendAppraisal())) {
                BigDecimal grade = Objects.isNull(e.getGrade()) ? BigDecimal.ZERO : e.getGrade();
                item.setGrade(grade);
                item.setScore(item.getScoreWeight() == 0 ? grade : grade.multiply(new BigDecimal(item.getScoreWeight() / 100).setScale(2, BigDecimal.ROUND_DOWN)));
                item.setReports(FileObjectUtil.toBOList(e.getReports()));
            }

            return item;
        }).collect(Collectors.toList());

        memberAppraisalItemRepository.saveAll(items);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> deleteMemberAppraisal(HttpHeaders headers, CommonIdsVO idsVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberAppraisalDO> memberAppraisalDOList = memberAppraisalRepository.findAllById(idsVO.getIds());
        if (CollectionUtils.isEmpty(memberAppraisalDOList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            if (!MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode().equals(memberAppraisalDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            memberAppraisalItemRepository.deleteByAppraisalId(memberAppraisalDO.getId());
        }

        memberAppraisalRepository.deleteAll(memberAppraisalDOList);

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            // 首页统计
            reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberRectifyOperateTypeEnum.TO_BE_SEND_NOTICE_COUNT.getCode(),
                    memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> publishMemberAppraisal(HttpHeaders headers, CommonIdsVO idsVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberAppraisalDO> memberAppraisalList = memberAppraisalRepository.findAllById(idsVO.getIds());
        if (CollectionUtils.isEmpty(memberAppraisalList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 状态校验
        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalList) {
            if (!MemberAppraisalStatusEnum.WAIT_PUBLISH.getCode().equals(memberAppraisalDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        // 首页统计和消息
        List<OperateNoticeVO> operateNoticeVOList = new ArrayList<>();
        List<SystemMessageRequest> systemMessageRequestList = new ArrayList<>();
        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalList) {
            // 工作流
            Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                    loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), ProcessTaskStatusEnum.AGREE.getCode());
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("会员考评发布,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            memberAppraisalDO.setStatus(result.getData().getInnerStatus());
            memberAppraisalDO.setTaskId(result.getData().getTaskId());
            memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

            memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                    MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), "");

            // 首页统计
            List<OperateNoticeVO> appraisalNoticeList = reportFeignService.buildReduceAndIncreaseVOList(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_PUBLISH_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_COMMIT_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());
            operateNoticeVOList.addAll(appraisalNoticeList);
            // 发送消息
            SystemMessageRequest appraisalSystemMessageList = messageFeignService.buildSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_summary_result, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
            systemMessageRequestList.add(appraisalSystemMessageList);

            Map<Long, List<MemberAppraisalItemDO>> userItems = memberAppraisalDO.getItems().stream()
                    .filter(item -> MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(item.getType()))
                    .collect(Collectors.groupingBy(item -> item.getByUser().getId()));

            for (Long userId : userItems.keySet()) {
                // 首页统计
                OperateNoticeVO operateNoticeVO = reportFeignService.buildIncreaseReportVO(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_SCORING_COUNT.getCode(),
                        memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());
                operateNoticeVOList.add(operateNoticeVO);

                // 发送消息
                SystemMessageRequest systemMessageRequest = messageFeignService.buildUserSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(), userId,
                        MessageTemplateCode.mc_appraisal_grade, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
                systemMessageRequestList.add(systemMessageRequest);
            }
        }

        reportFeignService.executeBatchReport(operateNoticeVOList);
        messageFeignService.batchSendSystemMessage(systemMessageRequestList);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> gradeMemberAppraisal(HttpHeaders headers, MemberAppraisalGradeVO gradeVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(gradeVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 提交的考评打分项目map
        Map<Long, MemberAppraisalItemGradeVO> itemGradeMap = gradeVO.getItems().stream().collect(Collectors.toMap(MemberAppraisalItemGradeVO::getId, e -> e, (e1, e2) -> e2));

        // 数据库中考评打分的项目
        List<MemberAppraisalItemDO> items = memberAppraisalDO.getItems();
        // 分组为属于用户打分的项目
        Map<Long, List<MemberAppraisalItemDO>> itemMap = items.stream().filter(item -> MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(item.getType())).collect(Collectors.groupingBy(item -> item.getByUser().getId()));
        // 属于该用户打分的项目
        List<MemberAppraisalItemDO> waitGradeItems = itemMap.get(loginUser.getUserId());
        if (CollectionUtils.isEmpty(waitGradeItems)) {
            return Wrapper.fail(ResponseCode.MC_MS_APPRAISAL_ITEM_NO_RELATION);
        }

        for (MemberAppraisalItemDO memberAppraisalItemDO : waitGradeItems) {
            MemberAppraisalItemGradeVO itemGradeVO = itemGradeMap.get(memberAppraisalItemDO.getId());
            memberAppraisalItemDO.setStatus(MemberAppraisalItemStatusEnum.GRADE_COMPLETE.getCode());
            if (Objects.nonNull(itemGradeVO)) {
                memberAppraisalItemDO.setGrade(itemGradeVO.getGrade());
                memberAppraisalItemDO.setReports(FileObjectUtil.toBOList(itemGradeVO.getReports()));
            } else {
                memberAppraisalItemDO.setGrade(BigDecimal.ZERO);
                memberAppraisalItemDO.setReports(Collections.emptyList());
            }
        }
        memberAppraisalItemRepository.saveAll(items);

        memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), MemberAppraisalStatusEnum.WAIT_GRADE.getCode(),
                MemberAppraisalItemStatusEnum.GRADE_COMPLETE.getMessage(), "考评打分", "");

        // 首页统计
        reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_SCORING_COUNT.getCode(),
                memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> submitMemberAppraisal(HttpHeaders headers, MemberAppraisalSubmitVO submitVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(submitVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 状态校验
        List<Integer> statusLists = Arrays.asList(MemberAppraisalStatusEnum.WAIT_SUBMIT.getCode(),
                MemberAppraisalStatusEnum.WAIT_AUDIT_1_REJECT.getCode(),
                MemberAppraisalStatusEnum.WAIT_AUDIT_2_REJECT.getCode());
        if (!statusLists.contains(memberAppraisalDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 考评打分项目map
        Map<Long, MemberAppraisalItemSubmitVO> itemSubmitMap = submitVO.getItems().stream().collect(Collectors.toMap(MemberAppraisalItemSubmitVO::getId, e -> e, (e1, e2) -> e2));

        // 需要用户打分的项目 userId - itemDOList
        Map<Long, List<MemberAppraisalItemDO>> userItemMap = memberAppraisalDO.getItems().stream()
                .filter(item -> MemberAppraisalItemTypeEnum.DEFINITION.getCode().equals(item.getType()))
                .collect(Collectors.groupingBy(item -> item.getByUser().getId()));

        // 更新的考评项目集合
        List<MemberAppraisalItemDO> saveItemList = new ArrayList<>();
        for (Map.Entry<Long, List<MemberAppraisalItemDO>> entry : userItemMap.entrySet()) {
            // 需要每个用户打分的考评项目
            List<MemberAppraisalItemDO> itemDOList = entry.getValue();
            // 是否通知首页统计待考评打分的数量
            boolean reportGrade = true;
            for (MemberAppraisalItemDO itemDO : itemDOList) {
                reportGrade = reportGrade && MemberAppraisalItemStatusEnum.WAIT_GRADE.getCode().equals(itemDO.getStatus());
                // 有提交的打分数据
                MemberAppraisalItemSubmitVO itemSubmitVO = itemSubmitMap.get(itemDO.getId());
                if (Objects.nonNull(itemSubmitVO)) {
                    itemDO.setScoreWeight(itemSubmitVO.getScoreWeight());
                    BigDecimal grade = Objects.isNull(itemSubmitVO.getGrade()) ? BigDecimal.ZERO : itemSubmitVO.getGrade();
                    itemDO.setGrade(grade);
                    itemDO.setScore(itemDO.getScoreWeight() == 0 ? grade : grade.multiply(new BigDecimal(itemDO.getScoreWeight() / 100).setScale(2, BigDecimal.ROUND_DOWN)));
                    itemDO.setTemplates(FileObjectUtil.toBOList(itemSubmitVO.getTemplates()));
                    itemDO.setReports(FileObjectUtil.toBOList(itemSubmitVO.getReports()));
                    itemDO.setStatus(MemberAppraisalItemStatusEnum.GRADE_COMPLETE.getCode());
                }
                saveItemList.add(itemDO);
            }

            if (reportGrade) {
                // 减少待考评打分的数量
                reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_SCORING_COUNT.getCode(),
                        memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());
            }
        }
        memberAppraisalItemRepository.saveAll(saveItemList);

        // 考评结果
        memberAppraisalDO.setTotalScore(submitVO.getTotalScore());
        memberAppraisalDO.setResult(submitVO.getResult());
        memberAppraisalDO.setNotifyMember(submitVO.getNotifyMember());
        memberAppraisalDO.setResultAttachments(FileObjectUtil.toBOList(submitVO.getResultAttachments()));
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员考评发布,调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberAppraisalDO.setStatus(result.getData().getInnerStatus());
        memberAppraisalDO.setTaskId(result.getData().getTaskId());
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        // 首页统计
        reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_COMMIT_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

        // 发送消息
        messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                MessageTemplateCode.mc_appraisal_result_audit_step_1, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));

        memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), "");

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditOneMemberAppraisal(HttpHeaders headers, CommonAgreeVO agreeVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(agreeVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberAppraisalStatusEnum.WAIT_AUDIT_1.getCode().equals(memberAppraisalDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), agreeVO.getAgree());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员考评审核,调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberAppraisalDO.setStatus(result.getData().getInnerStatus());
        memberAppraisalDO.setTaskId(result.getData().getTaskId());
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        if (EnableDisableStatus.ENABLE.getCode().equals(agreeVO.getAgree())) {
            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_result_audit_step_2, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
        } else {
            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_COMMIT_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_summary_result, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
        }

        memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), agreeVO.getReason());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditOneBatchMemberAppraisal(HttpHeaders headers, CommonIdsVO idsVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberAppraisalDO> memberAppraisalDOList = memberAppraisalRepository.findAllById(idsVO.getIds());
        if (CollectionUtils.isEmpty(memberAppraisalDOList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            if (!MemberAppraisalStatusEnum.WAIT_AUDIT_1.getCode().equals(memberAppraisalDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            // 工作流
            Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                    loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), EnableDisableStatus.ENABLE.getCode());
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("会员考评审核,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            memberAppraisalDO.setStatus(result.getData().getInnerStatus());
            memberAppraisalDO.setTaskId(result.getData().getTaskId());
            memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP1_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_result_audit_step_2, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));

            memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                    MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), "");
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditTwoMemberAppraisal(HttpHeaders headers, CommonAgreeVO agreeVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberAppraisalDO memberAppraisalDO = memberAppraisalRepository.findById(agreeVO.getId()).orElse(null);
        if (Objects.isNull(memberAppraisalDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberAppraisalStatusEnum.WAIT_AUDIT_2.getCode().equals(memberAppraisalDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 工作流
        Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), agreeVO.getAgree());
        if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
            log.error("会员考评审核,调用工作流失败: {}", result.getMessage());
            throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
        }

        memberAppraisalDO.setStatus(result.getData().getInnerStatus());
        memberAppraisalDO.setTaskId(result.getData().getTaskId());
        memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

        if (EnableDisableStatus.ENABLE.getCode().equals(agreeVO.getAgree())) {
            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_NOTICE_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_notification, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
        } else {
            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_COMMIT_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_summary_result, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));
        }

        memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), agreeVO.getReason());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> auditTwoBatchMemberAppraisal(HttpHeaders headers, CommonIdsVO idsVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberAppraisalDO> memberAppraisalDOList = memberAppraisalRepository.findAllById(idsVO.getIds());
        if (CollectionUtils.isEmpty(memberAppraisalDOList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            if (!MemberAppraisalStatusEnum.WAIT_AUDIT_2.getCode().equals(memberAppraisalDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalDOList) {
            // 工作流
            Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                    loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), EnableDisableStatus.ENABLE.getCode());
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("会员考评审核,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            memberAppraisalDO.setStatus(result.getData().getInnerStatus());
            memberAppraisalDO.setTaskId(result.getData().getTaskId());
            memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

            // 首页统计
            reportFeignService.executeReduceAndIncreaseReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_VALIFY_STEP2_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_NOTICE_COUNT.getCode(), memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            // 发送消息
            messageFeignService.sendSystemMessage(memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId(),
                    MessageTemplateCode.mc_appraisal_notification, Arrays.asList(memberAppraisalDO.getRole().getRoleName(), memberAppraisalDO.getMember().getName()));

            memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                    MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), "");
        }

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> notificationMemberAppraisal(HttpHeaders headers, CommonIdsVO idsVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        List<MemberAppraisalDO> memberAppraisalList = memberAppraisalRepository.findAllById(idsVO.getIds());
        if (CollectionUtils.isEmpty(memberAppraisalList)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        // 状态校验
        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalList) {
            if (!MemberAppraisalStatusEnum.WAIT_NOTIFICATION.getCode().equals(memberAppraisalDO.getStatus())) {
                return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
            }
        }

        for (MemberAppraisalDO memberAppraisalDO : memberAppraisalList) {
            // 工作流
            Wrapper<WorkflowTaskResultBO> result = workflowFeignService.execMemberProcess(ServiceConfig.MEMBER_APPRAISAL_PROCESS_KEY, memberAppraisalDO.getTaskId(),
                    loginUser.getMemberId(), loginUser.getMemberRoleId(), memberAppraisalDO.getId(), ProcessTaskStatusEnum.GOTO_NEXT_STEP.getCode());
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                log.error("会员考评通报,调用工作流失败: {}", result.getMessage());
                throw new BusinessException(ResponseCode.SERVICE_WORKFLOW_ERROR);
            }

            memberAppraisalDO.setStatus(result.getData().getInnerStatus());
            memberAppraisalDO.setTaskId(result.getData().getTaskId());
            memberAppraisalRepository.saveAndFlush(memberAppraisalDO);

            // 首页统计
            reportFeignService.executeReduceReport(OperateDataSourceEnum.MEMBER_KPI.getCode(), MemberKpiOperateTypeEnum.TO_BE_NOTICE_COUNT.getCode(),
                    memberAppraisalDO.getMember().getId(), memberAppraisalDO.getRole().getId());

            memberHistoryService.saveMemberAppraisalHistory(loginUser, memberAppraisalDO.getId(), memberAppraisalDO.getStatus(),
                    MemberAppraisalStatusEnum.getCodeMessage(memberAppraisalDO.getStatus()), result.getData().getOperation(), "");
        }

        return Wrapper.success();
    }
}
